package com.lms.busi.common.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.lms.busi.common.mapper.TLmsOrganizationMapper;
import com.lms.busi.common.service.ITLmsOrganizationService;
import com.lms.common.entity.TLmsOrganization;
import com.lms.common.pure.entity.ITreeNode;
import com.lms.common.pure.entity.TreeNode;
import com.lms.common.web.service.impl.WrapperServiceImpl;
import com.lms.common.web.utils.CheckEntityResult;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class TLmsOrganizationServiceImpl extends WrapperServiceImpl<TLmsOrganizationMapper, TLmsOrganization> implements ITLmsOrganizationService {
    @Override
    public IPage<?> queryMapper(Page<TLmsOrganization> page, Map<String, Object> p) {
        return this.baseMapper.query(page, p);
    }
    @Override
    public CheckEntityResult beforeInsert(TLmsOrganization entity) {
        CheckEntityResult result = CheckEntityResult.getInstance();
        if (StringUtils.isEmpty(entity.getName())) {
            result.add("name", "组织机构名称不能为空");
        }
        if (StringUtils.isEmpty(entity.getType())) {
            result.add("type", "组织机构名类型不能为空");
        }
        entity.setStatus(true);
        return result;
    }

    @Override
    public void toggleStatus(String id) {
        TLmsOrganization organization = this.getById(id);
        boolean status = organization.getStatus();
        organization.setStatus(!status);
        this.updateById(organization);
    }

    @Override
    public List<ITreeNode<String>> organizationaTreeList(boolean needVirtual) {
        QueryWrapper<TLmsOrganization> wrapper = new QueryWrapper<>();
        wrapper.orderByDesc("parent_id", "code");
        List<TLmsOrganization> organizationList = this.baseMapper.selectList(wrapper);
        List<ITreeNode<String>> result = new ArrayList<>();
        for (int i = 0; i < organizationList.size(); i++) {
            TLmsOrganization o = organizationList.get(i);
            if (o.getParentId() == null) {
                ITreeNode<String> node = new TreeNode<>();
                node.setId(o.getId());
                node.setName(o.getName());
                node.setType(o.getType());
                node.setVirtual(o.getVirtualDept());
                result.add(node);
                organizationList.remove(i);
                i--;
            }
        }
        result.forEach(r -> {
            executeTree(r, organizationList);
        });
        // 全部搞完了之后判断下虚拟部门，这个是要在页面上面去除的
        if (!needVirtual) {
            executeVirtualDept(result);
        }

        return result;
    }

    private void executeTree(ITreeNode<String> parentNode, List<TLmsOrganization> organizationList) {
        for (int i = organizationList.size() - 1; i >= 0; i--) {
            if (i >= organizationList.size()) {
                continue;
            }
            TLmsOrganization m = organizationList.get(i);
            if (parentNode.getId().equals(m.getParentId())) {
                ITreeNode<String> node = new TreeNode<>();
                node.setId(m.getId());
                node.setName(m.getName());
                node.setType(m.getType());
                node.setVirtual(m.getVirtualDept());
                parentNode.addChild(node);
                organizationList.remove(i);
                i++;
                executeTree(node, organizationList);
            }
        }
    }

    private void executeVirtualDept(List<ITreeNode<String>> result) {
        // 一开始确定下来size
        int size = result.size();
        Map<List<ITreeNode<?>>, ITreeNode<String>> waitRemoveNode = new HashMap<>();
        for (int i = size - 1; i >= 0; i--) {
            ITreeNode<String> node = result.get(i);
            List<ITreeNode<String>> children = node.getChildren();
            if (node.isVirtual()) {
                // 需要将该虚拟节点下的所有节点存放到真实节点中
                // 获取父节点
                ITreeNode<?> parent = node.getParent();
                List<ITreeNode<?>> parentChildren = parent.getChildren();
                // 取出其子节点放到父节点中去
                if (children != null && !children.isEmpty()) {
                    parentChildren.addAll(children);
                }
                waitRemoveNode.put(parentChildren, node);
            }
            if (children != null && !children.isEmpty()) {
                executeVirtualDept(children);
            }
        }
        waitRemoveNode.forEach(List::remove);
    }
}
